home *** CD-ROM | disk | FTP | other *** search
/ Programming Microsoft Visual Basic .NET / Programming Microsoft Visual Basic .NET (Microsoft Press)(X08-78517)(2002).bin / 06 interfaces and delegates / delegatedemo / module1.vb < prev   
Encoding:
Text File  |  2002-03-16  |  9.5 KB  |  255 lines

  1. Module Module1
  2.     
  3.     Sub Main()
  4.         ' Run one of the Textxxxx procedures below by uncommenting only one statement
  5.  
  6.         'TestFirstDelegate()
  7.         'TestLogDelegate()
  8.         'TestMultiCastDelegate()
  9.         'TestMulticastWithFunctions()
  10.         'TestCallbacks()
  11.         'TestAPICallback()
  12.  
  13.         ' You need these statements when running inside Visual Studio, so that
  14.         ' the Console window doesn't disappear
  15.         Console.WriteLine("")
  16.         Console.WriteLine(">>> press Enter to terminate the program <<<")
  17.         Console.ReadLine()
  18.     End Sub
  19.  
  20.     Delegate Sub OneArgSub(ByVal msg As String)
  21.  
  22.     Event LogToFile As LogWriter
  23.  
  24.     ' this procedure tests a simple delegate
  25.     Sub TestFirstDelegate()
  26.         ' declare and create the delegate
  27.         Dim deleg As OneArgSub
  28.         deleg = New OneArgSub(AddressOf DisplayMsg)
  29.  
  30.         ' This statement displays the "FooBar" string in the Console window.
  31.         deleg.Invoke("FooBar")                      ' => FooBar
  32.  
  33.         ' repeate the Invoke, this time displaying the message in a message box.
  34.         ' note that we use the shortened syntax to create the delegate
  35.         deleg = AddressOf PopupMsg
  36.         deleg.Invoke("FooBar")
  37.     End Sub
  38.  
  39.     ' Display a string in the Output window.
  40.     Sub DisplayMsg(ByVal msgText As String)
  41.         Console.WriteLine(msgText)
  42.     End Sub
  43.  
  44.     ' Display a string in a popup message box.
  45.     Sub PopupMsg(ByVal msgText As String)
  46.         Microsoft.VisualBasic.MsgBox(msgText)
  47.     End Sub
  48.  
  49.     Delegate Function One() As Integer
  50.  
  51.     Function FnOne() As Integer
  52.         Static counter As Integer
  53.         counter += 1
  54.         Debug.WriteLine("FnOne")
  55.         Return counter
  56.     End Function
  57.  
  58.     ' Test that you can do logging to the console or a file, depending
  59.     ' on a switch passed on the command line
  60.  
  61.     ' Define the delegate variable.
  62.     Delegate Sub LogWriter(ByVal Msg As String)
  63.     ' this is an instance of our class
  64.     Dim log As LogWriter
  65.     ' Define a stream writer.
  66.     Dim fw As System.IO.StreamWriter
  67.  
  68.     Sub TestLogDelegate()
  69.         ' Get command line arguments.
  70.         Dim args() As String = Environment.GetCommandLineArgs
  71.  
  72.         If args.Length > 1 Then
  73.             ' If the command line contains a file name, open that file.
  74.             fw = New System.IO.StreamWriter(args(1))
  75.             ' Have the delegate point to the stream's WriteLine method.
  76.             log = New LogWriter(AddressOf fw.WriteLine)
  77.         Else
  78.             ' If no argument has been specified, send to the console.
  79.             log = New LogWriter(AddressOf Console.WriteLine)
  80.         End If
  81.  
  82.         ' use the Method name and reflection to display info on the target method.
  83.         Console.WriteLine("Target method: " & log.Method.Name)
  84.  
  85.         Call DoTheRealJob()
  86.  
  87.         ' This is necessary to flush the output buffer.        
  88.         If Not (fw Is Nothing) Then fw.Close()
  89.     End Sub
  90.  
  91.     ' a sample routine that uses tracing
  92.     Sub DoTheRealJob()
  93.         log("Start of program")
  94.         ' ....
  95.         log("In the middle of the program.")
  96.         ' ...
  97.         log("End of program")
  98.     End Sub
  99.  
  100.     ' this procedure tests a multicast delegate - it displays a trace message
  101.     ' to the Console *and* to a file (if an argument is passed on the 
  102.     ' command line)
  103.  
  104.     Sub TestMultiCastDelegate()
  105.         ' Always log to the Console.
  106.         log = AddressOf Console.WriteLine
  107.         ' Define another delegate
  108.         Dim log2 As LogWriter
  109.  
  110.         ' Get command line arguments.
  111.         Dim args() As String = Environment.GetCommandLineArgs
  112.  
  113.         If args.Length > 1 Then
  114.             ' The command line contains a file name.
  115.             fw = New System.IO.StreamWriter(args(1))
  116.             ' Create a second delegate that points to the stream's WriteLine method.
  117.             log2 = AddressOf fw.WriteLine
  118.             ' combine it with the existing delegate.
  119.             log = DirectCast(log.Combine(log, log2), LogWriter)
  120.         End If
  121.  
  122.         Call DoTheRealJob()
  123.  
  124.         ' This is necessary to flush the output buffer.        
  125.         If Not (fw Is Nothing) Then fw.Close()
  126.  
  127.         ' List the names of all the target methods.
  128.         Console.WriteLine("")
  129.         Console.WriteLine("List of target methods:")
  130.  
  131.         ' List all the delegates in a multi-cast delegate. 
  132.         ' (Note that Delegate is a reserved word and must be enclosed in square brackets.)
  133.         Dim delegs() As [Delegate] = log.GetInvocationList
  134.  
  135.         ' Get the list of individual delegates in a multi-cast delegates.
  136.         Dim d As [Delegate]
  137.         For Each d In delegs
  138.             Console.WriteLine(d.Method.Name)
  139.         Next
  140.  
  141.         ' Change the log delegate so that it doesn't log to file any longer.
  142.         log = DirectCast(log.Remove(log, log2), LogWriter)
  143.         ' This method only display a log message to the console.
  144.         log("Application ended")
  145.     End Sub
  146.  
  147.     ' this procedure shows that it is possible to call functions
  148.     ' through multicast delegates
  149.  
  150.     Sub TestMulticastWithFunctions()
  151.         Dim d As New One(AddressOf FnOne)
  152.         Dim d2 As New One(AddressOf FnOne)
  153.         d = DirectCast(d.Combine(d, d2), One)
  154.  
  155.         Debug.WriteLine(d.Invoke)
  156.     End Sub
  157.  
  158.     ' this procedure show how to use delegates for callbacks
  159.  
  160.     Sub TestCallbacks()
  161.         ' print the names of all directories under c:\Docs
  162.         TraverseDirectoryTree("C:\DOCS", AddressOf DisplayDirectoryName)
  163.     End Sub
  164.  
  165.     ' a function that complies with the TraverseDirectoryTree_CBK syntax
  166.     Function DisplayDirectoryName(ByVal path As String) As Boolean
  167.         Console.WriteLine(path)
  168.         If path = "C:\DOCS\LIBRI\OOP" Then Return True
  169.     End Function
  170.  
  171.     ' a delegate that defines the syntax of the function whose address
  172.     ' can be passed to TraverseDirectoryTree - if this function returns True
  173.     ' then the enumeration should be stopped
  174.     Delegate Function TraverseDirectoryTree_CBK(ByVal dirName As String) As Boolean
  175.  
  176.     ' a reusable procedure that traverse a directory tree and calls back the caller
  177.     ' for each new directory
  178.     Sub TraverseDirectoryTree(ByVal path As String, ByVal callback As TraverseDirectoryTree_CBK)
  179.         Dim dirName As String
  180.         Static nestLevel As Integer       ' nesting nestLevel
  181.         Static isCanceled As Boolean      ' True if the client isCanceled the enumeration
  182.  
  183.         nestLevel += 1
  184.  
  185.         For Each dirName In System.IO.Directory.GetDirectories(path)
  186.             ' call back the program to notify this directory
  187.             isCanceled = callback.Invoke(dirName)
  188.             If isCanceled Then Exit For
  189.             ' call recursively this routine
  190.             TraverseDirectoryTree(dirName, callback)
  191.         Next
  192.  
  193.         nestLevel -= 1
  194.         ' reset isCanceled if we are about to return to the user
  195.         If nestLevel = 0 Then isCanceled = False
  196.     End Sub
  197.  
  198.     Sub TestAPICallback()
  199.         EnumWindows(AddressOf EnumWindows_CBK, 0)
  200.     End Sub
  201. End Module
  202.  
  203. ' this module tests using callback delegates with Windows API calls
  204.  
  205. Module EnumWindowsDemo
  206.     Delegate Function EnumWindows_Callback(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
  207.  
  208.     Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As EnumWindows_Callback, ByVal lParam As Integer) As Integer
  209.     Public Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Integer, ByVal lpEnumFunc As EnumWindows_Callback, ByVal lParam As Integer) As Integer
  210.     Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Integer, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
  211.     Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Integer, ByVal lpString As System.Text.StringBuilder, ByVal cch As Integer) As Integer
  212.  
  213.     ' The callback routine, common to both EnumWindows and EnumChildWindows.
  214.     ' the argument passed in lParam is the indent level.
  215.  
  216.     Function EnumWindows_CBK(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
  217.         ' display information on this window, with correct indentation
  218.         Console.WriteLine(New String(" "c, lParam * 3) & WindowDescription(hWnd))
  219.         ' then display all child windows, but indent them to the right
  220.         EnumChildWindows(hWnd, AddressOf EnumWindows_CBK, lParam + 1)
  221.         ' Return 1 to continue enumeration.
  222.         Return 1
  223.     End Function
  224.  
  225.     ' return a windows description given its hWnd
  226.  
  227.     Function WindowDescription(ByVal hWnd As Integer) As String
  228.         Dim text As String
  229.         text = WindowText(hWnd)
  230.  
  231.         WindowDescription = "[" & Right$("0000000" & Hex$(hWnd), 8) & "] " _
  232.             & WindowClassName(hWnd)
  233.         If Len(text) > 0 Then
  234.             WindowDescription &= " - """ & text & """"
  235.         End If
  236.     End Function
  237.  
  238.     ' Return the caption/text of a window.
  239.  
  240.     Function WindowText(ByVal hWnd As Integer) As String
  241.         Dim buffer As New System.Text.StringBuilder(256)
  242.         Dim length As Integer
  243.         length = GetWindowText(hWnd, buffer, buffer.Capacity)
  244.         WindowText = buffer.ToString.Substring(0, length)
  245.     End Function
  246.  
  247.     Function WindowClassName(ByVal hWnd As Integer) As String
  248.         Dim buffer As New System.Text.StringBuilder(256)
  249.         Dim length As Integer
  250.         length = GetClassName(hWnd, buffer, buffer.Capacity)
  251.         WindowClassName = buffer.ToString.Substring(0, length)
  252.     End Function
  253.  
  254. End Module
  255.